#include "LogManager.h"
#include "Exception.h"
#include <algorithm>

namespace PVM
{
	template<> LogManager* Singleton<LogManager>::ms_Singleton = 0;
	LogManager* LogManager::getSingletonPtr(void)
	{
		return ms_Singleton;
	}
	LogManager& LogManager::getSingleton(void)
	{
		assert(ms_Singleton); return (*ms_Singleton);
	}
	
	LogManager::LogManager()
	{
		mDefaultLog = NULL;
	}
	
	LogManager::~LogManager()
	{
		PVM_LOCK_AUTO_MUTEX
		
		LogList::iterator i;
		for (i = mLogs.begin(); i != mLogs.end(); ++i)
		{
			delete i->second;
		}
	}
	
	Log* LogManager::createLog(const std::string& name, bool defaultLog, bool debuggerOutput,
							   bool suppressFileOutput)
	{
		PVM_LOCK_AUTO_MUTEX
		
		Log* newLog = new Log(name, debuggerOutput, suppressFileOutput);
		if (!mDefaultLog || defaultLog)
		{
			mDefaultLog = newLog;
		}
		
		mLogs.insert(LogList::value_type(name, newLog));
		
		return newLog;
	}
	
	Log* LogManager::getDefaultLog()
	{
		PVM_LOCK_AUTO_MUTEX
		return mDefaultLog;
	}
	
	Log* LogManager::setDefaultLog(Log* newLog)
	{
		PVM_LOCK_AUTO_MUTEX
		Log* oldLog = mDefaultLog;
		mDefaultLog = newLog;
		return oldLog;
	}
	
	Log* LogManager::getLog(const std::string& name)
	{
		PVM_LOCK_AUTO_MUTEX
		LogList::iterator i = mLogs.find(name);
		if (i != mLogs.end())
			return i->second;
		else
			PVM_EXCEPT(Exception::ERR_INVALIDPARAMS, "Log not found. ", "LogManager::getLog");
	}
	
	void LogManager::destroyLog(const std::string& name)
	{
		LogList::iterator i = mLogs.find(name);
		if (i != mLogs.end())
		{
			if (mDefaultLog == i->second)
			{
				mDefaultLog = 0;
			}
			delete i->second;
			mLogs.erase(i);
		}
		
		if (!mDefaultLog && !mLogs.empty())
		{
			mDefaultLog = mLogs.begin()->second;
		}
	}
	
	void LogManager::destroyLog(Log* log)
	{
		destroyLog(log->getName());
	}
	
	void LogManager::logMessage(const std::string& message, LogMessageLevel lml, bool maskDebug)
	{
		PVM_LOCK_AUTO_MUTEX
		if (mDefaultLog)
		{
			mDefaultLog->logMessage(message, lml, maskDebug);
		}
	}
	
	void LogManager::setLogDetail(LoggingLevel ll)
	{
		PVM_LOCK_AUTO_MUTEX
		if (mDefaultLog)
		{
			mDefaultLog->setLogDetail(ll);
		}
	}
	
	Log::Stream LogManager::stream(LogMessageLevel lml, bool maskDebug)
	{
		PVM_LOCK_AUTO_MUTEX
		if (mDefaultLog)
			return mDefaultLog->stream(lml, maskDebug);
		else
			PVM_EXCEPT("Default log not found. ", "LogManager::stream");
	}
}
